---
type: integration
title: '@astrojs/node'
description: 了解如何使用 @astrojs/node 适配器来部署你的 Astro 项目。
sidebar:
  label: Node
githubIntegrationURL: 'https://github.com/withastro/astro/tree/main/packages/integrations/node/'
category: adapter
i18nReady: true
---

import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro'
import Since from '~/components/Since.astro';
import { Tabs, TabItem } from '@astrojs/starlight/components';

此适配器允许 Astro 将你的 [按需渲染路由及其功能](/zh-cn/guides/on-demand-rendering/) 部署到 Node 目标，包括 [服务器群岛](/zh-cn/guides/server-islands/)，[actions](/zh-cn/guides/actions/) 以及 [sessions](/zh-cn/guides/sessions/)。

如果你将 Astro 用作静态站点构建器，则不需要适配器。

## 为什么选择 Astro Node.js

[Node.js](https://nodejs.org/zh-cn) 是用于服务器端代码的 JavaScript 运行时。 @astrojs/node 可以在独立模式下使用，也可以作为其他 http 服务器（例如 [Express](https://expressjs.com/)）的中间件。

## 安装

Astro 包含了一个 `astro add` 命令，用于自动设置官方集成。如果你愿意，可以改为[手动安装集成](#手动安装)。

使用 `astro add` 命令将 Node 适配器添加到你的 Astro 项目中，以启用按需渲染。这将一步到位地安装 `@astrojs/node` 并对你的 `astro.config.*` 文件进行适当的修改。

<PackageManagerTabs>
  <Fragment slot="npm">
  ```sh
  npx astro add node
  ```
  </Fragment>
  <Fragment slot="pnpm">
  ```sh
  pnpm astro add node
  ```
  </Fragment>
  <Fragment slot="yarn">
  ```sh
  yarn astro add node
  ```
  </Fragment>
</PackageManagerTabs>

现在，你可以启用 [对每个页面的按需渲染](/zh-cn/guides/on-demand-rendering/#启用按需渲染)，或者将你的构建输出配置设置为 `output: 'server'` 从而 [默认对所有页面都进行服务器端渲染](/zh-cn/guides/on-demand-rendering/#server-模式)。

### 手动安装

首先，使用适合你的包管理器将 Node 适配器添加到你的项目依赖中。
    
<PackageManagerTabs>
  <Fragment slot="npm">
  ```sh
  npm install @astrojs/node
  ```
  </Fragment>
  <Fragment slot="pnpm">
  ```sh
  pnpm add @astrojs/node
  ```
  </Fragment>
  <Fragment slot="yarn">
  ```sh
  yarn add @astrojs/node
  ```
  </Fragment>
</PackageManagerTabs>

然后，将适配器添加到 `astro.config.*` 文件中：

 ```js title="astro.config.mjs" ins={2,5-7}
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
  adapter: node({
    mode: 'standalone',
  }),
});
```

## 配置

@astrojs/node 可以通过将选项传递给适配器函数来配置。以下选项可用：

### `mode`
<p>
**类型：** `'middleware' | 'standalone'` <br />
</p>

控制适配器是构建为 `middleware` 模式还是 `standalone` 模式。

* `middleware` 模式允许将构建的输出用作另一个 Node.js 服务器的中间件，例如 Express.js 或 Fastify。
* `standalone` 构建到服务器，随着入口模块的运行会自动启动。这使你可以更轻松地部署到主机，而无需任何额外的代码。

```js title="astro.config.mjs" {6}
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
  adapter: node({
    mode: 'middleware',
  }),
});
```

### `experimentalDisableStreaming`

<p>
**类型：** `boolean` <br />
**默认值：** `false`<br />
<Since v="9.3.0" pkg="@astrojs/node" />
</p>

对于按需渲染的页面，禁用 Astro 的默认 [HTML 流式传输](/zh-cn/guides/on-demand-rendering/#html-流式传输)。

HTML 流式传输有助于提升性能，通常能为访客提供更好的体验。在大多数情况下，不建议禁用此功能。

但当你确实需要禁用 HTML 流式传输时（例如你的主机仅支持在 CDN 层级缓存非流式 HTML），可以通过以下方式覆盖默认行为：

```js title="astro.config.mjs" {7}
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
  adapter: node({
    mode: 'standalone',
    experimentalDisableStreaming: true,
  }),
});
```

### `experimentalStaticHeaders`

<p>
  **类型：** `boolean` <br />
  **默认值：** `false`<br />
  <Since v="9.3.0"  pkg="@astrojs/node"/>
</p>

启用后，当 Astro 功能（如内容安全策略）提供 `Response` 对象时，适配器将使用该对象提供预渲染页面的头部信息。

例如，当启用 [实验性的内容安全策略](/zh-cn/reference/experimental-flags/csp/) 时，可以使用 `experimentalStaticHeaders` 将 CSP `headers` 添加 `Response` 对象，而不是创建 `<meta>` 元素：

```js title="astro.config.mjs" {10}
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
  experimental: {
    csp: true
  },
  adapter: node({
    mode: 'standalone',
    experimentalStaticHeaders: true,
  })
});
```

### `experimentalErrorPageHost`

<p>
  **类型：** `string | URL` <br />
  **默认值：** `undefined`<br />
  <Since v="9.4.0" pkg="@astrojs/node"/>
</p>

指定用于加载预渲染 [自定义错误页面](/zh-cn/basics/astro-pages/#自定义-404-错误页面) 的替代主机。

Astro 需要能够加载你的 404 页面以便在响应中返回。默认情况下，Astro 会从与请求所指向的主机相同的主机加载预渲染的自定义错误页面。例如，如果对 `https://example.com/nonexistent-page` 发起请求，Astro 将尝试从 `https://example.com/404.html` 加载预渲染错误页面。

当你的自定义错误页面必须从不同主机加载时（例如服务器运行在反向代理之后或在可能无法访问外部主机 URL 的容器中），请使用 `experimentalErrorPageHost` 。当从本地主机加载预渲染错误页面比通过公共互联网加载更高效时，也可以使用此选项。

该值可以是字符串或 URL 对象。它必须是一个完整的符合格式的 URL，包括协议（例如， `http://localhost:4321` ）。Astro 将始终从根路径加载预渲染错误页面，任何路径或查询参数都将被忽略。

```js
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
  adapter: node({
    // 从本地主机加载页面，而不是公共网址。
    experimentalErrorPageHost: 'http://localhost:4321',
  })
});
```

## 用法

首先，[执行构建](/zh-cn/guides/deploy/#在本地构建站点)。根据选择的模式（见上文），执行以下相应的步骤：

### 中间件

服务器入口文件默认构建为 `./dist/server/entry.mjs`。该模块导出一个 `处理程序（handler）` 函数，可以与任何支持 Node `请求（request）` 和 `响应（response）` 对象的框架一起使用。

例如，使用 Express：

```js title="run-server.mjs"
import express from 'express';
import { handler as ssrHandler } from './dist/server/entry.mjs';

const app = express();
// 根据 astro.config.mjs 中的 `base` 选项进行更改。
// 它们应该匹配。默认值为"/"。
const base = '/';
app.use(base, express.static('dist/client/'));
app.use(ssrHandler);

app.listen(8080);
```

或者使用 Fastify (>4)：

```js title="run-server.mjs"
import Fastify from 'fastify';
import fastifyMiddie from '@fastify/middie';
import fastifyStatic from '@fastify/static';
import { fileURLToPath } from 'node:url';
import { handler as ssrHandler } from './dist/server/entry.mjs';

const app = Fastify({ logger: true });

await app
  .register(fastifyStatic, {
    root: fileURLToPath(new URL('./dist/client', import.meta.url)),
  })
  .register(fastifyMiddie);
app.use(ssrHandler);

app.listen({ port: 8080 });
```

此外，你还可以传入一个对象，以便使用 `Astro.locals` 或 Astro 中间件访问该对象：

```js title="run-server.mjs"
import express from 'express';
import { handler as ssrHandler } from './dist/server/entry.mjs';

const app = express();
app.use(express.static('dist/client/'));
app.use((req, res, next) => {
  const locals = {
    title: 'New title',
  };

  ssrHandler(req, res, next, locals);
});

app.listen(8080);
```


请注意，中间件模式不提供文件服务。你需要配置 HTTP 框架来完成这项工作。默认情况下，客户端资产写入 `./dist/client/`。

### 独立

在独立模式下，服务器在入口文件运行时启动。默认情况下，它被构建为 `./dist/server/entry.mjs`。你可以运行它：

```sh
node ./dist/server/entry.mjs
```

对于独立模式，服务器除了处理页面和 API 路由之外还处理文件服务。

#### 自定义主机和端口

你可以覆盖独立服务器运行的主机和端口，通过在运行时将它们作为环境变量进行传递：

```sh
HOST=0.0.0.0 PORT=4321 node ./dist/server/entry.mjs
```

#### HTTPS

默认情况下，独立服务器使用 HTTP。如果前面有一个执行 HTTPS 的代理服务器，则能更好的工作。如果你需要独立服务器本身来运行 HTTPS，你需要提供 SSL 密钥和证书。

你可以通过环境变量 `SERVER_CERT_PATH` 和 `SERVER_KEY_PATH` 传递密钥和证书的路径。这就是在 bash 中传递它们的方式：

```bash
SERVER_KEY_PATH=./private/key.pem SERVER_CERT_PATH=./private/cert.pem node ./dist/server/entry.mjs
```

#### 资源文件

在独立模式下，你的 `dist/client/` 文件夹中的资源文件将通过独立服务器提供服务。但你可能会将这些资源部署到 CDN 上，在这种情况下，服务器实际上则不会为它们提供服务。但是在某些情况下，比如内网站点，直接从应用服务器提供静态资源文件则是可行的。

`dist/client/_astro/` 文件夹中的资源文件由 Astro 构建。这些资源文件都是带有哈希命名的，因此可以设置长时间的缓存标头。所以在内部，适配器为这些资源添加了如下的标头信息：

```
Cache-Control: public, max-age=31536000, immutable
```

### Sessions

Astro [Session API](/zh-cn/guides/sessions/) 允许你在请求间，轻松地存储用户数据。该功能可用于用户数据和偏好选项，购物车内容，资格鉴权。不同于 cookie 存储，这里不存在对数据大小的限制，并且可以将其存储在不同的设备上。

当使用 Netlify 适配器时，Astro 将自动配置 [Netlify Blobs](https://docs.netlify.com/blobs/overview/) 用于会话（session）存储。如果你更倾向于使用其他的会话存储驱动，你可以在 Astro config 中指定。更多细节请参见 [`session` 配置参考](/zh-cn/reference/configuration-reference/#sessiondriver)。

## 环境变量

在运行时使用 [`astro:env`](/zh-cn/guides/environment-variables/#类型安全的环境变量) secrets 或 `process.env` 时 ，Astro 和适配器都不会为你加载环境变量。

一些主机可能会在构建时和运行时通过其仪表板暴露你配置的环境变量。请查阅你所用主机在特定平台上设置和使用环境变量的文档。

在自托管时，你可以通过 CLI 命令或配置文件按需加载环境变量：

<Tabs>
  <TabItem label="Inline">
  ```shell
  DB_HOST=... DB_PASSWORD=... node ./dist/server/entry.mjs
  ```
  </TabItem>
  <TabItem label="dotenvx">
  ```shell
  npx dotenvx run -- node ./dist/server/entry.mjs
  ```
  </TabItem>
  <TabItem label="Docker">
  ```docker title="Dockerfile"
  FROM node:lts AS runtime
  WORKDIR /app

  COPY . .

  RUN npm install
  RUN npm run build

  ENV DB_HOST=...
  ENV DB_PASSWORD=...
  CMD node ./dist/server/entry.mjs
  ```
  </TabItem>
</Tabs>
